
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <time.h>
#include <HTTPClient.h>
#include "HMACSHA256.h"
#include "mytasks.h"
#include "myFuncs.h"
#include "mymqtt.h"
#include "TFTDriver.h"
/* 全局变量 */
// RTOS 内核变量
QueueHandle_t cloudFrame_queue = nullptr; // 云端数据帧缓存队列


/*************************核心0******************************/

#define TEMP_MAX 1024
void HB_handle_task(void *parameter)
{
  StaticJsonDocument<1024> doc; // 这个值不确定
  char temp[TEMP_MAX];
  HTTPClient httpClient;
  String report_url = "http://home.fowo.eu.org:30080/air";
  while (1)
  {
    if (WiFi.isConnected())
    {
      // 更新设备在IotDA的属性
      doc["wind"] = tft.getWind();
      doc["state"] = tft.getStatus();
      doc["temperature"] = tft.getTemp();
      doc["mode"] = tft.getMode();
      serializeJson(doc, temp, measureJson(doc) + 1);
      doc.clear();
      httpClient.begin(report_url);
		  httpClient.addHeader("Content-Type", "application/json");
      ESP_LOGD(pcTaskGetName(nullptr), "Report properties:%s", temp);
      httpClient.POST(temp);
    }
    else
      Serial.println("WiFi disconnected");
    delay(1000);
  }
}

/* 云端消息处理任务 */
void cloud_news_handle_task(void *parameter){
  CloudFrame cFrame;
  uint32_t index;
  BaseType_t ret;
  DynamicJsonDocument doc(1024); // 声明JSON对象
  WiFi.begin(WIFI_SSID, WIFI_PASS); // 尝试连接 wifi
  ESP_LOGI("", "Waiting to link wifi: %s\n", WIFI_SSID);
  // 确保 WiFi 正常连接
  uint8_t count = 0;
  while(WiFi.status() != WL_CONNECTED){
    ESP_LOGI("", "Watting wifi connected...");
    delay(1000);
    count++;
    if(count > 10)
      esp_restart();
  }
  ESP_LOGD("", "Wifi connected: %s", WIFI_SSID);
  // 心跳包上报任务
  xTaskCreatePinnedToCore(HB_handle_task, "HB_handle_task", 1024*5, nullptr, 3, nullptr, 0);
  IoTDA_client.setServer(IOTDA_IP, IOTDA_PORT); // 设置连接IoTDA的MQTT服务
  IoTDA_client.setKeepAlive(60);
  IoTDA_client.setCallback(IoTDA_callback); // 设置回调函数入口

  // 获取UTC时间
  time_t time_now; // 存储标准格式时间
  char time_buffer[10+1]; // 存储YYYYMMDDHH的UTC时间戳
  char IotDA_clientId[strlen(IOTDA_DEVICEID)+5+10+1];
  char IotDA_password_encrypted[32*2+1]; // 存放
  configTime(0*3600, 0, "ntp3.aliyun.com");
  count = 0;
  do
  {
    ESP_LOGI(pcTaskGetName(nullptr), "Waiting for time sync...%d", time(nullptr));
    delay(1000);
    count++;
  } while (time(nullptr) < 1703669609 && count<7); // 等待时间加载完毕
  if(count >= 7){
    esp_restart();
  }
  xTaskCreatePinnedToCore(LED_task, "LED_task", 1024*1, NULL, 2, NULL, 0); // 创建任务
  while(1){
    // 保障 MQTT 常驻
    if(!IoTDA_client.loop()){
      time_now = time(nullptr);
      strftime(time_buffer, 11, "%Y%m%d%H", localtime(&time_now)); // 提取关键时间信息
      sprintf(IotDA_clientId, "%s_0_0_%s", IOTDA_DEVICEID, time_buffer); // 合并出客户端ID
      ESP_LOGD(pcTaskGetName(nullptr), "IotDA_clientId is %s", IotDA_clientId);

      // 将 MQTT 连接密码加密
      HMACSHA256_encrypt(IotDA_password_encrypted, (uint8_t *)IOTDA_DEVICESRCRET, (uint8_t *)time_buffer);
      ESP_LOGD(pcTaskGetName(nullptr), "IotDA_password_encrypted is %s", IotDA_password_encrypted);

      // 重连IoTDA服务器
      mqtt_reconnect(IotDA_clientId, IOTDA_DEVICEID, IotDA_password_encrypted, IOTDA_MSG_DOWN_TOPIC);
    }
    else
    {
      ret = xQueueReceive(cloudFrame_queue, &cFrame, 5 / portTICK_RATE_MS); // 等10ms队列数据帧信息
      if (ret != pdTRUE || cFrame.data_len == 0){
        static uint16_t touch_x, touch_y;
        if (tft.getTouch(&touch_x, &touch_y))
        {
          ESP_LOGD("Touch","%d\t%d\n", touch_x, touch_y);
        }
        continue;
      }
      // 先判断是否为一个正常的 json 包
      if (cFrame.real_data[0] != '{' || cFrame.real_data[cFrame.data_len - 1] != '}'){
        ESP_LOGW(pcTaskGetName(nullptr), "Received data is not a JSON package");
        continue;
      }
      // 解析JSON
      deserializeJson(doc, cFrame.real_data);
      if (doc.containsKey("state"))
        if(doc["state"].as<uint8_t>()){
            tft.open();
          vTaskDelay(10);
        }
        else{
          tft.close();
          vTaskDelay(10);
        }
      if(doc.containsKey("temperature")){
//        vTaskSuspendAll();
        tft.changeTemp(doc["temperature"].as<uint8_t>());
//        xTaskResumeAll();
        vTaskDelay(300);
      }
      if(doc.containsKey("mode")){
        tft.changeMode(doc["mode"].as<uint8_t>());
        vTaskDelay(10);
      }
      if(doc.containsKey("wind")){
        tft.changeWind(doc["wind"].as<uint8_t>());
        vTaskDelay(10);
      }
    }
  }
}

//指示用灯光 任务
void LED_task(void *parameter){
  uint8_t count = 0;
  uint8_t inver_flag = 1;
  while(1){
    LEDB_OFF;
    LEDA_ON;
    vTaskDelay(4*count+50);
    LEDB_ON;
    LEDA_OFF;
    vTaskDelay(4*count+50);
    if(inver_flag){
      count++;
      if(count == 50)
        inver_flag = 0;
    }
    else{
      count--;
      if(count == 0)
        inver_flag = 1;
    }
  }
}
